import vnode from './vnode.js';

/**
 * 编写一个低配版的h函数，必须接收三个参数。
 * 有这个三种形式：
 * 1、h('div', {}, '文字')
 * 2、h('div', {}, [])
 * 3、h('div', {}, h())
 * @param {String} sel 元素名字符串或是选择器
 * @param {Object} data 用于设置元素的属性、事件等的数据
 * @param {...} c 不确定类型
 **/
export default function (sel, data, c) {
    /* 检查参数的个数 */
    if (arguments.length != 3)
        throw new Error('对不起，这个个低配版的h函数，必须传入三个参数！')
    /* 检查参数c的类型 */
    if (typeof c == 'string' || typeof c == 'number') {
        /* 说明调用h函数的形态1 */
        return vnode(sel, data, undefined, c, undefined);
    } else if (Array.isArray(c)) {  /* 说明调用h函数的形态2 */
        /* 定义变量，用于保存子元素 */
        let children = [];
        /* 变量子元素的c，收集到children数组 */
        for (let index = 0; index < c.length; index++) {
            const element = c[index];
            if (!(typeof element == 'object' && element.hasOwnProperty('sel'))) {
                throw new Error('传入的数组参数中有项不是h函数')
            }
            /* 这里不用执行element，因为我们再调用h函数的时候，就是在执行h函数。这里直接收集就好 */
            children.push(element)
        }
        /* 循环结束后，说明children收集完毕了，此时返回虚拟节点，这个虚拟节点是有children属性的。 */
        return vnode(sel, data, children, undefined, undefined);
    } else if (typeof c == 'object' && element.hasOwnProperty('sel')) {  /* 说明调用h函数的形态3 */
        let children = [c];
        return vnode(sel, data, children, undefined, undefined);
    } else {
        throw new Error('传入的三个参数类型不对')
    }
}